home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 147 / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin / games / hexrev / crx / think.c < prev   
C/C++ Source or Header  |  2000-07-07  |  18KB  |  753 lines

  1. /***************************************************
  2.  
  3.   think.c : 六角リバーシ思考ルーチン
  4.  
  5.         Copyright (C) 1997 - 2000 by Makoto Hiroi
  6.  
  7. -CRX ver by 電魔団\shoryu 2000
  8.  
  9. ****************************************************/
  10. #include  "hexrev.h"
  11.  
  12. /* 関数宣言 */
  13. static int search_white( int, int, int );
  14. static int finish_white( int, int );
  15.  
  16. extern const char  reverse_table[546][11];
  17. extern const short zahyou[SIZE][2];
  18.  
  19. /* 盤面の定義 */
  20. static char  board[SIZE];
  21. static short black;
  22. static short white;
  23. static int   space[SIZE];          /* 探索領域をセットする */
  24. static int   space_count;          /* カウンタ */
  25. static int   value_table[SIZE];    /* 評価値をセットする */
  26. static int   depth;                /* 探索手数 */
  27.  
  28. static int  w1;      /* 位置数の重み */
  29. static int  w2;      /* 場所の重み */
  30.  
  31. /* 初期化データ */
  32. static const char    init_table[SIZE] = {
  33.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  34.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  35.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  36.   FREE, FREE, FREE, FREE, WHITE, BLACK, FREE,  FREE, FREE, FREE,
  37.   FREE, FREE, FREE, FREE, BLACK, C_RES, WHITE, FREE, FREE, FREE,
  38.   FREE, FREE, FREE, FREE, FREE,  WHITE, BLACK, FREE, FREE, FREE,
  39.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  40.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  41.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  42.   FREE,
  43. };
  44.  
  45.  
  46. /*@@*/
  47. /**終了済みターン数を返す
  48.  */
  49. int getTurnNum()
  50. {
  51.     return( black+white );
  52. }
  53. /**board番号numに駒pを置く
  54.  */
  55. void setBoard(num,p)
  56. int num,p;
  57. {
  58.     board[num]=p;
  59. }
  60. /*@@*/
  61.  
  62.  
  63.  
  64. /* 石数の表示 */
  65. void print_stones( void )
  66. {
  67.     _dos_c_locate( 22, 1 );
  68.     printf( "黒 %2d 個 : 白 %2d 個", black, white );
  69.     fflush( stdout );
  70. }
  71.  
  72. /* データの初期化 */
  73. void init_data( void )
  74. {
  75.     int        i;
  76.     const char    *ptr = init_table;
  77.     for( i = 0; i < SIZE; i++, ptr++ ){
  78.           board[i] = *ptr;
  79.     }
  80.     white = 3;
  81.     black = 3;    //4-C_RES
  82.     /* 駒を置く */
  83.     _iocs_apage( 0 );
  84.     _iocs_wipe();        /* グラフィッククリア */
  85.     draw_piece( 34, WHITE );
  86.     draw_piece( 35, BLACK );
  87.     draw_piece( 44, BLACK );
  88.     draw_piece( 45, C_RES );    /*@@*/
  89.     draw_piece( 46, WHITE );
  90.     draw_piece( 55, WHITE );
  91.     draw_piece( 56, BLACK );
  92.     /* 石数の表示 */
  93.     print_stones();
  94. }
  95.  
  96. /* 駒を裏返すことができるか */
  97. int check_reverse( int num )
  98. {
  99.   int    i, result = 0;
  100.   /* 6 方向をチェックする */
  101.   for( i = 0; i < DIR; i++ ){
  102.     int wc = 0, bc = 0, wf = FALSE, bf = FALSE;
  103.     const char  *ptr = reverse_table[num * DIR + i];
  104.     if( *ptr == -1 ) break;        /* 終了 */
  105.     do {
  106.       char content = board[*ptr];
  107.       if( (content==FREE)||(content==C_RES)  ){        /*@@*/
  108.         break;            /* 空きエリア */
  109.       } else if( content == BLACK ){
  110.         bf = TRUE;
  111.     if( !wf ) wc++;
  112.       } else if( content == WHITE ){        /*@@*/
  113.     wf = TRUE;
  114.         if( !bf ) bc++;
  115.       }
  116.     } while( *(++ptr) != -1 );
  117.     if( bf && bc ) result |= PUT_BLACK;
  118.     if( wf && wc ) result |= PUT_WHITE;
  119.     if( result == (PUT_BLACK|PUT_WHITE) ) break;
  120.   }
  121.   return result;
  122. }
  123.  
  124. /* 石を置ける場所をセットする */
  125. static int set_space_postion( void )
  126. {
  127.   int    i, c;
  128.   for( i = c = 0; i < SIZE; i++ ){
  129.     if( (board[i]==FREE)||(board[i]==C_RES) ){    /*@@*/
  130.       space[c] = i;
  131.       value_table[c++] = NO_VALUE;
  132.     }
  133.   }
  134.   return space_count = c;
  135. }
  136.  
  137. /* 駒を置ける場所をセットする */
  138. static int set_piece_postion( void )
  139. {
  140.     int  i, c;
  141.     for( i = c = 0; i < SIZE; i++ ){
  142.         if( (board[i]==FREE)||(board[i]==C_RES) ){        /*@@*/
  143.             space[c] = i;
  144.             value_table[c++] = NO_VALUE;
  145.         }
  146.     }
  147.     return c;
  148. }
  149.  
  150.  
  151. /* 座標から位置を求める */
  152. int get_postion( int x, int y )
  153. {
  154.     int  i, j = set_piece_postion();
  155.     for( i = 0; i < j; i++ ){
  156.         int  n = space[i];
  157.         int  x1 = zahyou[n][0];
  158.         int  y1 = zahyou[n][1];
  159.         if( (x1 - 17 <= x) && (x <= x1 + 17) &&
  160.             (y1 - 17 <= y) && (y <= y1 + 17)){
  161.             return n;
  162.         }
  163.     }
  164.     return -1;
  165. }
  166.  
  167.  
  168. /* 指し手があるか */
  169. int check_move( int piece )
  170. {
  171.   int  i;
  172.   int  k = (piece == BLACK) ? PUT_BLACK : PUT_WHITE;
  173.   for( i = 0; i < SIZE; i++ ){
  174.     if( board[i] != FREE ) continue;
  175.     if( board[i] == C_RES ) continue;    /*@@*/
  176.     if( check_reverse( i ) & k ) return TRUE;
  177.   }
  178.   return FALSE;
  179. }
  180.  
  181. /* 駒を反転する */
  182. int reverse_piece( int num, int piece, char *result )
  183. {
  184.   int    i, count = 0;
  185.   if( board[num] != FREE ) return 0; /* 石を置くことはできないよ */
  186.   /* 6 方向をチェックする */
  187.   for( i = 0; i < DIR; i++ ){
  188.     int  c = count, flag = FALSE;
  189.     const char *ptr = &(reverse_table[num * DIR + i][0]);
  190.     if( *ptr == -1 ) break;
  191.     do {
  192.       int content = board[*ptr];
  193.       if( (content==FREE)||(content==C_RES) ){    /*@@*/
  194.     break;            /* 空きエリア */
  195.       } else if( content == piece ){
  196.     flag = TRUE; break;    /* 同種の駒を見つけたよ */
  197.       } else {
  198.     result[c++] = *ptr;    /* 異種の駒 */
  199.       }
  200.     } while( *(++ptr) != -1 );
  201.  
  202.     if( flag && (c > count) ){
  203.       count = c;        /* 裏返しができたよ */
  204.     }
  205.   }
  206.   result[count] = -1;           /* 終端セット */
  207.   if( count ){            /* 駒を置くことができるよ */
  208.     board[num] = piece;
  209.     for( i = 0; i < count; i++ ){
  210.       board[ result[i] ] = piece;
  211.     }
  212.     if( piece == BLACK ){
  213.       black += count + 1;
  214.       white -= count;
  215.     } else {
  216.       white += count + 1;
  217.       black -= count;
  218.     }
  219.   }
  220.   return count;
  221. }
  222.  
  223. /* 重みテーブル */
  224. static const int weight_table[SIZE] = {
  225.   1000, 20, 20, 20, 20, 1000,
  226.     20,  0,  1,  1,  1,  0, 20,
  227.     20,  1,  1,  1,  1,  1,  1, 20,
  228.     20,  1,  1,  1,  1,  1,  1,  1, 20,
  229.     20,  1,  1,  1,  1,  1,  1,  1,  1, 20,
  230.   1000,  0,  1,  1,  1,  1,  1,  1,  1,  0, 1000,
  231.     20,  1,  1,  1,  1,  1,  1,  1,  1, 20,
  232.     20,  1,  1,  1,  1,  1,  1,  1, 20,
  233.     20,  1,  1,  1,  1,  1,  1, 20,
  234.     20,  0,  1,  1,  1,  0, 20,
  235.   1000, 20, 20, 20, 20, 1000,
  236. };
  237.  
  238. /* 位置テーブル */
  239. #define CORNER 1
  240.  
  241. static const char postion_table[SIZE] = {
  242.   CORNER, 2, 0, 0, 3, CORNER,
  243.   13, 0, 0, 0, 0, 5, 20,
  244.    0, 0, 0, 0, 0, 0, 0, 0, 
  245.    0, 0, 0, 0, 0, 0, 0, 0, 0, 
  246.   21, 0, 0, 0, 0, 0, 0, 0, 0, 29,
  247.   CORNER, 40, 0, 0, 0, 0, 0, 0, 0, 50, CORNER,
  248.   61, 0, 0, 0, 0, 0, 0, 0, 0, 69,
  249.    0, 0, 0, 0, 0, 0, 0, 0, 0,
  250.    0, 0, 0, 0, 0, 0, 0, 0,
  251.   70,85, 0, 0, 0, 90, 77,
  252.   CORNER, 87, 0, 0, 88, CORNER,
  253. };
  254.  
  255. /* 評価関数(黒有利が正となる) */
  256. static int value_func( int turn )
  257. {
  258.   static const char corner[6] = {0, 5, 40, 50, 85, 90 };
  259.   static const char revision[6][3] = {
  260.      7,  1,  6,  11,  4, 12,  41, 30, 51,  49, 39, 60,
  261.     79, 78, 86,  83, 84, 89,
  262.   };
  263.   static const int rev_value[3] = {
  264.     150, 100, 100
  265.   }; 
  266.   int    bv = 0, wv = 0, bc = 0, wc = 0, i;
  267.   for( i = 0; i < SIZE; i++ ){
  268.     switch( board[i] ){
  269.       case BLACK:
  270.         bv += weight_table[i]; break;
  271.       case WHITE:
  272.         wv += weight_table[i]; break;
  273.       case FREE:
  274.     if( weight_table[i] ){
  275.       int put = check_reverse( i );
  276.       if( put & PUT_BLACK ){
  277.         if( turn == BLACK && postion_table[i] == CORNER ){
  278.           bv += 250;
  279.         } else {
  280.           bc++;
  281.         }
  282.       }
  283.       if( put & PUT_WHITE ){
  284.         if( turn == WHITE && postion_table[i] == CORNER ){
  285.           wv += 250;
  286.         } else {
  287.           wc++;
  288.         }
  289.       }
  290.     }
  291.         break;
  292.       }
  293.   }
  294.   /* 隅の補正 */
  295.   for( i = 0; i < 6; i++ ){
  296.     int j;
  297.     int n = corner[i];
  298.     int k = board[n];
  299.     if( k == FREE ){
  300.       /* 隅が空いているよ */
  301.       for( j = 0; j < 3; j++ ){
  302.     int p = revision[i][j];
  303.     int v = rev_value[j];
  304.         switch( board[ p ] ){
  305.           case BLACK:
  306.         if( board[ postion_table[p] ] != BLACK ) wv += v;
  307.             break;
  308.           case WHITE:
  309.         if( board[ postion_table[p] ] != WHITE ) bv += v;
  310.             break;
  311.         }
  312.       }
  313.     } else {
  314.       /* 辺の安定性を評価(まだ不完全) */
  315.       for( j = 0; j < 2; j++ ){
  316.     int  v = 0;
  317.     const char *ptr = reverse_table[n * DIR + j];
  318.     while( *ptr != -1 ){
  319.       if( k != board[*ptr++] ) break;
  320.       v += 90;
  321.     }
  322.     if( v == 450 ) v /= 2;    /* 5 つとも同じ石 */
  323.     if( k == WHITE ) wv += v;
  324.     else             bv += v;
  325.       }
  326.     }
  327.   }
  328.   /* 石数は逆に評価する */
  329.   return (bc - wc) * w1 + (bv - wv) + (white - black) * w2;
  330. }
  331.  
  332. /* 結果判定 */
  333. int result_value( int flag )
  334. {
  335.   int    value;
  336.   int    wc = white;
  337.   int    bc = black;
  338.   if( wc + bc == SIZE || flag == TRUE ){
  339.     if( wc == bc ){
  340.       value = 0;        /* 引き分け */
  341.     } else if( bc > wc ){
  342.       value = MAX_VALUE + bc - wc; /* 黒勝ち */
  343.     } else {
  344.       value = MIN_VALUE + bc - wc; /* 白勝ち */
  345.     }
  346.   } else if( wc == 0 ){
  347.     value = MAX_VALUE + bc;    /* 白全滅 */
  348.   } else if( bc == 0 ){
  349.     value = MIN_VALUE - wc;    /* 黒全滅 */
  350.   } else {
  351.     value = NO_VALUE;        /* 決着がついていないよ */
  352.   }
  353.   return value;
  354. }
  355.  
  356.  
  357. /* ミニマックスによる探索 */
  358. static int search_black( int his, int limit, int pass_flag )
  359. {
  360.   int i, point = MIN_LIMIT;
  361.   short save_white = white;
  362.   short save_black = black;
  363.   if( his == depth ){
  364.     return value_func( BLACK );
  365.   }
  366.   for( i = 0; i < space_count; i++ ){
  367.     int value, pos = space[i];
  368.     char piece_buffer[SIZE/2];
  369.  
  370.     /* 駒が置いてあるかチェックする */
  371.     if( board[pos] != FREE ) continue;
  372.     /* 駒を置く */
  373.     if( !reverse_piece( pos, BLACK, piece_buffer ) ) continue;
  374.  
  375.     /* 終了チェック */
  376.     if( (value = result_value( FALSE )) == NO_VALUE ){
  377.       /* 相手の手番 */
  378.       value = search_white( his + 1, point, FALSE );
  379.     }
  380.     /* 駒を元に戻す */
  381.     {
  382.       char *ptr = piece_buffer;
  383.       board[pos] = FREE;
  384.       white = save_white;
  385.       black = save_black;
  386.       do {
  387.     board[*ptr++] = WHITE;
  388.       } while( *ptr != -1 );
  389.     }
  390.     /* ミニマックス */
  391.     if( value > point ){
  392.       point = value;
  393.     }
  394.     /* αβ枝刈 */
  395.     if( point > limit ){
  396.       break;
  397.     }
  398.   }
  399.   if( point == MIN_LIMIT ){
  400.     /* 打つ手がなかった */
  401.     if( pass_flag == TRUE ){
  402.       /* 相手も打つ手なし */
  403.       point = result_value( TRUE ); /* 終了 */
  404.     } else {
  405.       /* パスだよ */
  406.       point = search_white( his, MIN_LIMIT, TRUE );
  407.     }
  408.   }
  409.   return point;
  410. }
  411.  
  412. /* 白番 */
  413. static int search_white( int his, int limit, int pass_flag )
  414. {
  415.   int   i, point = MAX_LIMIT;
  416.   short save_white = white;
  417.   short save_black = black;
  418.   if( his == depth ){
  419.     return value_func( WHITE );
  420.   }
  421.   for( i = 0; i < space_count; i++ ){
  422.     int value, pos = space[i];
  423.     char piece_buffer[SIZE/2];
  424.  
  425.     /* 駒が置いてあるかチェックする */
  426.     if( board[pos] != FREE ) continue;
  427.     /* 駒を置く */
  428.     if( !reverse_piece( pos, WHITE, piece_buffer ) ) continue;
  429.  
  430.     /* 終了チェック */
  431.     if( (value = result_value( FALSE )) == NO_VALUE ){
  432.       /* 再帰する */
  433.       value = search_black( his + 1, point, FALSE );
  434.     }
  435.     /* 駒を元に戻す */
  436.     {
  437.       char *ptr = piece_buffer;
  438.       board[pos] = FREE;
  439.       white = save_white;
  440.       black = save_black;
  441.       do {
  442.     board[*ptr++] = BLACK;
  443.       } while( *ptr != -1 );
  444.     }
  445.  
  446.     /* ミニマックス */
  447.     if( point > value ){
  448.       point = value;
  449.     }
  450.     /* αβ枝刈 */
  451.     if( point < limit ){
  452.       break;
  453.     }
  454.   }
  455.   if( point == MAX_LIMIT ){
  456.     /* 打つ手がなかった */
  457.     if( pass_flag == TRUE ){
  458.       /* 相手も打つ手なし */
  459.       point = result_value( TRUE ); /* 終了 */
  460.     } else {
  461.       /* パスだよ */
  462.       point = search_black( his, MAX_LIMIT, TRUE );
  463.     }
  464.   }
  465.   return point;
  466. }
  467.  
  468. /* 読み切り専用 */
  469. static int finish_black( int limit, int pass_flag )
  470. {
  471.   int i, point = MIN_LIMIT;
  472.   short save_white = white;
  473.   short save_black = black;
  474.   for( i = 0; i < space_count; i++ ){
  475.     int value, pos = space[i];
  476.     char piece_buffer[SIZE/2];
  477.  
  478.     /* 駒が置いてあるかチェックする */
  479.     if( board[pos] != FREE ) continue;
  480.     /* 駒を置く */
  481.     if( !reverse_piece( pos, BLACK, piece_buffer ) ) continue;
  482.  
  483.     /* 終了チェック */
  484.     if( black + white < SIZE ){
  485.       value = finish_white( point, FALSE );
  486.     } else {
  487.       value = black - white;
  488.     }
  489.     /* 駒を元に戻す */
  490.     {
  491.       char *ptr = piece_buffer;
  492.       board[pos] = FREE;
  493.       white = save_white;
  494.       black = save_black;
  495.       do {
  496.     board[*ptr++] = WHITE;
  497.       } while( *ptr != -1 );
  498.     }
  499.     /* ミニマックス */
  500.     if( value > point ){
  501.       point = value;
  502.     }
  503.     /* αβ枝刈 */
  504.     if( point > limit ){
  505.       break;
  506.     }
  507.   }
  508.   if( point == MIN_LIMIT ){
  509.     /* 打つ手がなかった */
  510.     if( pass_flag == TRUE ){
  511.       /* 相手も打つ手なし */
  512.       point = black - white; /* 終了 */
  513.     } else {
  514.       /* パスだよ */
  515.       point = finish_white( MIN_LIMIT, TRUE );
  516.     }
  517.   }
  518.   return point;
  519. }
  520.  
  521. /* 白番 */
  522. static int finish_white( int limit, int pass_flag )
  523. {
  524.   int   i, point = MAX_LIMIT;
  525.   short save_white = white;
  526.   short save_black = black;
  527.   for( i = 0; i < space_count; i++ ){
  528.     int  value, pos = space[i];
  529.     char piece_buffer[SIZE];
  530.  
  531.     /* 駒が置いてあるかチェックする */
  532.     if( board[pos] != FREE ) continue;
  533.     /* 駒を置く */
  534.     if( !reverse_piece( pos, WHITE, piece_buffer ) ) continue;
  535.  
  536.     /* 終了チェック */
  537.     if( black + white < SIZE ){
  538.       value = finish_black( point, FALSE );
  539.     } else {
  540.       value = black - white;
  541.     }
  542.     /* 駒を元に戻す */
  543.     {
  544.       char *ptr = piece_buffer;
  545.       board[pos] = FREE;
  546.       white = save_white;
  547.       black = save_black;
  548.       do {
  549.     board[*ptr++] = BLACK;
  550.       } while( *ptr != -1 );
  551.     }
  552.  
  553.     /* ミニマックス */
  554.     if( point > value ){
  555.       point = value;
  556.     }
  557.     /* αβ枝刈 */
  558.     if( point < limit ){
  559.       break;
  560.     }
  561.   }
  562.   if( point == MAX_LIMIT ){
  563.     /* 打つ手がなかった */
  564.     if( pass_flag == TRUE ){
  565.       /* 相手も打つ手なし */
  566.       point = black - white;
  567.     } else {
  568.       /* パスだよ */
  569.       point = finish_black( MAX_LIMIT, TRUE );
  570.     }
  571.   }
  572.   return point;
  573. }
  574.  
  575. /* 単純挿入ソート */
  576. static void sort( int limit )
  577. {
  578.   int i, j;
  579.   for( i = 1; i < limit; i++ ){
  580.     int tmp_pos = space[i];
  581.     int tmp_value = value_table[i];
  582.     for( j = i - 1; j >= 0 && tmp_value > value_table[j]; j-- ){
  583.       space[j + 1] = space[j];
  584.       value_table[j + 1] = value_table[j];
  585.     }
  586.     space[j + 1] = tmp_pos;
  587.     value_table[j + 1] = tmp_value;
  588.   }
  589. }
  590.  
  591. static void rsort( int limit )
  592. {
  593.   int i, j;
  594.   for( i = 1; i < limit; i++ ){
  595.     int tmp_pos = space[i];
  596.     int tmp_value = value_table[i];
  597.     for( j = i - 1; j >= 0 && tmp_value < value_table[j]; j-- ){
  598.       space[j + 1] = space[j];
  599.       value_table[j + 1] = value_table[j];
  600.     }
  601.     space[j + 1] = tmp_pos;
  602.     value_table[j + 1] = tmp_value;
  603.   }
  604. }
  605.  
  606. /* 反復深化による探索 */
  607. static void search_move( int turn, int level )
  608. {
  609.   int limit = set_space_postion();
  610.   short save_white = white;
  611.   short save_black = black;
  612.  
  613.   if( level <= 4 ){
  614.     depth = level;
  615.   } else {
  616.     depth = 4;    /* 5, 6 手先読みは反復深化を使う */
  617.   }
  618.   for( ; depth <= level; depth++ ){
  619.     int i, point = (turn == BLACK ? MIN_LIMIT : MAX_LIMIT);
  620.     for( i = 0; i < limit; i++ ){
  621.       int value, pos = space[i];
  622.       char piece_buffer[SIZE/2];
  623.       if( board[pos] != FREE ) continue;
  624.  
  625.       /* 石を置く */
  626.       if( !reverse_piece( pos, turn, piece_buffer ) ) continue;
  627.       /* 終了チェック */
  628.       if( (value = result_value( FALSE )) == NO_VALUE ){
  629.     if( turn == BLACK ){
  630.       value = search_white( 1, point, FALSE );
  631.     } else {
  632.       value = search_black( 1, point, FALSE );
  633.     }
  634.       }
  635.       value_table[i] = value;
  636.       /* 元に戻す */
  637.       {
  638.     char *ptr = piece_buffer;
  639.     char piece = (turn == BLACK ? WHITE : BLACK);
  640.     white = save_white;
  641.     black = save_black;
  642.     board[pos] = FREE;
  643.     do {
  644.       board[*ptr++] = piece;
  645.     } while( *ptr != -1 );
  646.       }
  647.       if( (turn == BLACK && value > point) ||
  648.       (turn == WHITE && value < point) ){
  649.     point = value;
  650.       }
  651.     }
  652.     if( depth <= 4 ){
  653.       /* NO_VALUE を後ろに集める */
  654.       rsort( limit );
  655.       /* NO_VALUE を除外する */
  656.       while( value_table[limit - 1] == NO_VALUE ) limit--;
  657.     }
  658.     if( turn == BLACK ) sort( limit ); else rsort( limit );
  659.   }
  660. }
  661.  
  662. /* 読み切り */
  663. static void finish_move( int turn )
  664. {
  665.   int   limit = set_space_postion();
  666.   short save_white = white;
  667.   short save_black = black;
  668.   int   i, point = (turn == BLACK ? MIN_LIMIT : MAX_LIMIT);
  669.   for( i = 0; i < limit; i++ ){
  670.     int value, pos = space[i];
  671.     char piece_buffer[SIZE];
  672.  
  673.     /* 駒が置いてあるかチェックする */
  674.     if( board[pos] != FREE ) continue;
  675.     /* 駒を置く */
  676.     if( !reverse_piece( pos, turn, piece_buffer ) ) continue;
  677.  
  678.     /* 終了チェック */
  679.     if( black + white < SIZE ){
  680.       if( turn == BLACK ){
  681.     value = finish_white( point, FALSE );
  682.       } else {
  683.     value = finish_black( point, FALSE );
  684.       }
  685.     } else {
  686.       value = black - white;
  687.     }
  688.     value_table[i] = value;
  689.     /* 駒を元に戻す */
  690.     {
  691.       char *ptr = piece_buffer;
  692.       char piece = (turn == BLACK ? WHITE : BLACK);
  693.       board[pos] = FREE;
  694.       white = save_white;
  695.       black = save_black;
  696.       do {
  697.     board[*ptr++] = piece;
  698.       } while( *ptr != -1 );
  699.     }
  700.     if((turn == BLACK && value > point) ||
  701.        (turn == WHITE && value < point) ){
  702.       point = value;
  703.     }
  704.   }
  705.   /* NO_VALUE を後ろに集める */
  706.   rsort( limit );
  707.   /* NO_VALUE を除外する */
  708.   while( value_table[limit - 1] == NO_VALUE ) limit--;
  709.   if( turn == BLACK ) sort( limit ); else rsort( limit );
  710. }  
  711.  
  712.  
  713. /* 指手の決定 */
  714. static int decide_move( int turn )
  715. {
  716.   int move = 0, i = 1, v = value_table[0];
  717.   while( v == value_table[i] ) i++;
  718.   /* 同じ値の手がある */
  719.   if( i > 1 ){
  720.     /* 乱数で指手を決定する */
  721.     move = rand() % i;
  722.   }
  723.   return space[move];
  724. }
  725.  
  726. /* 反復深化による探索 */
  727. int select_move( int turn, int level )
  728. {
  729.   int num  = white + black;
  730.   static int finish_table[6] = {
  731.     7, 8, 9, 10, 11, 12,        /* 7 はダミー */
  732.   };
  733.   /* 重みの設定 */
  734.   if( num + level > 60 ){
  735.     w1 = 30; w2 = 20;
  736.   } else if( num + level > 30 ){
  737.     w1 = 20; w2 = 20;
  738.   } else {
  739.     w1 = 20; w2 = 10;
  740.   }
  741.   /* 読み切りモードのチェック */
  742.   if( (SIZE - num) <= finish_table[level] ){
  743.     finish_move( turn );
  744.   } else {
  745.     search_move( turn, level );
  746.   }
  747.   /* 指手の決定 */
  748.   return decide_move( turn );
  749. }
  750.  
  751. /* end of file */
  752.  
  753.